package indi.zjh.dp.vc;

import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.dom4j.DocumentException;

import indi.zjh.dp.error.UnsuportedFieldException;
import indi.zjh.dp.orm.MethodFactory;
import indi.zjh.dp.orm.RelationClass;
import indi.zjh.dp.startup.Application;
import indi.zjh.dp.startup.Constant;
import indi.zjh.dp.util.CodecUtil;
import indi.zjh.dp.util.FileUtil;
import indi.zjh.dp.util.SystemCmd;

public class Commit implements Serializable{
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	// 版本提交时间戳
	protected long timestamp;
	// 版本描述
	protected String desc;
	// 版本的唯一标识
	protected String sha1;
	// 该版本的所有业务文件对象, 检出后该对象才有值
	protected Map<String, FileObject> fileObject = null;
	
	/**
	 * 获取检出后的业务文件对象
	 * @return
	 */
	public Map<String, FileObject> getFileObjectMap()
	{
		return this.fileObject;
	}
	
	/**
	 * 提交当前的业务类代码
	 * @param desc: 版本描述
	 * @return 是否提交成功, 如果业务没有变化, 提交失败
	 * @throws Exception 
	 * @throws DocumentException 
	 */
	public boolean submit(String desc) throws DocumentException, Exception
	{

		Iterator<Entry<String, RelationClass>> iter = VersionControl.getInstance().getRunningTimeVersion().getRelationClassIterator();
		int relationClassCount = VersionControl.getInstance().getRunningTimeVersion().getRelationClassCount();
		int noChangeRelationClassCount = 0;
		while(iter.hasNext())
		{
			Entry<String, RelationClass> entry = iter.next();
			String clsName = entry.getKey();
			RelationClass rClass = entry.getValue();
			if(!VersionControl.getInstance().addToRepository(rClass))
				noChangeRelationClassCount++;
		}
		// 业务类没有发生变化
		if(relationClassCount == noChangeRelationClassCount)
			return false;
		VersionControl.getInstance().writeFileObject();
		VersionControl.getInstance().readFileObject();
		
		// 初始化提交对象
		this.desc = desc;
		this.timestamp = new Date().getTime();
		this.sha1 = CodecUtil.sha1(this.timestamp + this.desc);
		
		VersionControl.getInstance().addCommit(this);
		VersionControl.getInstance().writeCommitObject();
		return true;
	}
	
	/**
	 * 获取提交对象的sha1
	 * @return
	 */
	public String getSha1Text()
	{
		return this.sha1;
	}
	
	/**
	 * 检出指定的版本
	 * @param dstDir: 检出到目录
	 * @param clear: 是否要删除已存在目录下的所有文件
	 * @return: 检出版本
	 * @throws IOException 
	 * @throws InstantiationException 
	 * @throws IllegalAccessException 
	 * @throws UnsuportedFieldException 
	 * @throws ClassNotFoundException 
	 */
	public Version checkout(String dstDir, boolean isClear) throws IllegalAccessException, InstantiationException, IOException, UnsuportedFieldException, ClassNotFoundException
	{
		MethodFactory.init();
		File oldDir = new File(dstDir);
		if(isClear)
		{
			if(oldDir.exists())
			{
				FileUtil.deleteDirectory(oldDir);
			}
		}
		
		oldDir.mkdir();
		// 需要检出的业务类对象, 类路径 -> 类文件对象
		this.fileObject = new HashMap<String, FileObject>();
		try
		{
			Iterator<FileObject> iter = VersionControl.getInstance().iterator();
			while(iter.hasNext())
			{
				FileObject fo = iter.next();
				if(this.timestamp >= fo.getTimestamp())
				{
					if(!this.fileObject.containsKey(fo.getSrcFilePath()))
					{
						this.fileObject.put(fo.getSrcFilePath(), fo);
					}
					else
					{
						FileObject org = this.fileObject.get(fo.getSrcFilePath());
						if(org.getTimestamp() < fo.getTimestamp())
						{
							this.fileObject.put(fo.getSrcFilePath(), fo);
						}
					}
				}
			}
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		
		// 获取待检出的业务代码类
		Set<String> fileSet = this.fileObject.keySet();
		Iterator<String> fileIter = fileSet.iterator();
		while(fileIter.hasNext())
		{
			String srcPath = fileIter.next();
			FileObject fo = this.fileObject.get(srcPath);
			File fromFile = new File(fo.getRepositoryFilePath());
			String toFilePath = fo.getSrcFilePath().replace(Constant.BUSINESS_SOURCE_DIRECTORY, dstDir);
			File toFile = new File(toFilePath);
			
			File parentDir = new File(toFile.getParent());
			parentDir.mkdirs();

			try {
				FileUtil.copy(fromFile, toFile);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		Version v = new Version(this, dstDir);
		return v;
	}
	
	/**
	 * 获取提交对象的描述
	 * @return
	 */
	public String getDesc()
	{
		return this.desc;
	}
	
	public long getTimestamp()
	{
		return this.timestamp;
	}
	
	public String toString()
	{
		return this.timestamp + ":" + this.desc + ":" + this.sha1;
	}
}
